﻿using System;
using System.Collections.Generic;
using Character;
using WzhAddon.DanLookAt;
using WzhAddon.DHHPlugIn;
using RootMotion.FinalIK;
using Studio;
using UnityEngine;

namespace WzhAddon
{
	public class AdvancedIKController : MonoBehaviour
	{
		public ChaControl charInfo;
		public OCIChar studioChara;
		public IKCtrl rigController;
		public DanLookAtController danLookController;
		public IKMorphFix ikMorphFix;
		public Dictionary<string, AdvancedIKControlNode> nodes = new Dictionary<string, AdvancedIKControlNode>();
		public Dictionary<int, AdvancedIKControlNode> nodesMap = new Dictionary<int, AdvancedIKControlNode>();
		public float weight = 1f;
		public static AdvancedIKController Install(OCIChar studioChara)
		{
			ChaControl chaControl = studioChara.charInfo;
			AdvancedIKController advancedIKController = AdvancedIKController.Get(chaControl);
			if (advancedIKController == null)
			{
				advancedIKController = chaControl.gameObject.AddComponent<AdvancedIKController>();
				advancedIKController.Init(studioChara);
			}
			return advancedIKController;
		}

		public static AdvancedIKController Get(ChaControl chara)
		{
			return chara.gameObject.GetComponent<AdvancedIKController>();
		}
		public void Init(OCIChar studioChara)
		{
			this.studioChara = studioChara;
			this.charInfo = studioChara.charInfo;
			this.rigController = studioChara.ikCtrl;
			this.InstallIKControlNodes();
			BaseMgr<AdvancedIKMgr>.Instance.activeControllers.Add(this);
			this.danLookController = DanLookAtController.Get(studioChara);
			this.ikMorphFix = IKMorphFix.Install(studioChara);
		}
		public bool dhhCheck()
		{
			if (this.charInfo.sex == 1)
			{
				int id = this.charInfo.human.wears.GetWearData(WEAR_TYPE.SHOES).id;
				if (BaseMgr<HighHeelRunTime>.Instance.ShoeDataMap.ContainsKey(id)) return true;
			}
			this.ikMorphFix.dhhEnable = false;
			return false;
		}

		private void InstallIKControlNodes()
		{
			IKCtrl ikCtrl = this.studioChara.ikCtrl;
			IKSolverFullBodyBiped solver = this.studioChara.fullBodyIK.solver;
			Dictionary<int, IKEffector> dictionary = new Dictionary<int, IKEffector>
			{{0,solver.bodyEffector},{1,solver.leftShoulderEffector},{3,solver.leftHandEffector},{4,solver.rightShoulderEffector},
				{6,solver.rightHandEffector},{7,solver.leftThighEffector},{9,solver.leftFootEffector},{10,solver.rightThighEffector},{12,solver.rightFootEffector}};
			Dictionary<int, FBIKChain> dictionary2 = new Dictionary<int, FBIKChain> { { 2, solver.leftArmChain }, { 5, solver.rightArmChain }, { 8, solver.leftLegChain }, { 11, solver.rightLegChain } };
			string[] array = new string[]
			{
				"Hips",
				"Shoulder(L)",
				"Elbow(L)",
				"Hand(L)",
				"Shoulder(R)",
				"Elbow(R)",
				"Hand(R)",
				"Thigh(L)",
				"Knee(L)",
				"Foot(L)",
				"Thigh(R)",
				"Knee(R)",
				"Foot(R)"
			};
			foreach (int num in dictionary.Keys)
			{
				OCIChar.IKInfo ikinfo = this.studioChara.listIKTarget[num];
				GuideObject guideObject = ikinfo.guideObject;
				IKEffector target = dictionary[num];
				Transform transformTarget = guideObject.transformTarget;
				AdvancedIKControlNode advancedIKControlNode = transformTarget.gameObject.AddComponent<AdvancedIKControlNode>();
				advancedIKControlNode.controller = this;
				advancedIKControlNode.Init(ikinfo, guideObject, target, array[num]);
				this.nodes.Add(num.ToString("00") + "_" + transformTarget.name, advancedIKControlNode);
				this.nodesMap[num] = advancedIKControlNode;
			}
			foreach (int num2 in dictionary2.Keys)
			{
				OCIChar.IKInfo ikinfo2 = this.studioChara.listIKTarget[num2];
				GuideObject guideObject2 = ikinfo2.guideObject;
				FBIKChain bendGoal = dictionary2[num2];
				Transform transformTarget2 = guideObject2.transformTarget;
				AdvancedIKControlNode advancedIKControlNode2 = transformTarget2.gameObject.AddComponent<AdvancedIKControlNode>();
				advancedIKControlNode2.controller = this;
				advancedIKControlNode2.Init(ikinfo2, guideObject2, bendGoal, array[num2]);
				this.nodes.Add(num2.ToString("00") + "_" + transformTarget2.name, advancedIKControlNode2);
				this.nodesMap[num2] = advancedIKControlNode2;
			}
		}

		private void Update()
		{
			this.UpdateWeight();
		}

		public void UpdateWeight()
		{
			FullBodyBipedIK fullBodyIK = this.studioChara.fullBodyIK;
			if (!fullBodyIK.isActiveAndEnabled) return;
			IKSolverFullBodyBiped solver = fullBodyIK.solver;
			for (int i = 0; i < 5; i++)
			{
				if (this.studioChara.oiCharInfo.activeIK[i] == false) continue;
				OIBoneInfo.BoneGroup group = (OIBoneInfo.BoneGroup)(1 << i);
				this.UpdateWeightGroup(group, true);
			}
		}

		public virtual void UpdateWeightGroup(OIBoneInfo.BoneGroup _group, bool _active)
		{
			IKSolverFullBodyBiped solver = this.studioChara.fullBodyIK.solver;
			switch (_group)
			{
				case OIBoneInfo.BoneGroup.Body:
					float num = this.weight * this.nodesMap[0].weight;
					float num2 = this.weight * this.nodesMap[0].rotationWeight;
					solver.spineMapping.twistWeight = num2;
					solver.SetEffectorWeights(FullBodyBipedEffector.Body, num, num2);
					return;
				case OIBoneInfo.BoneGroup.RightLeg:
					solver.rightLegMapping.weight = this.weight * this.nodesMap[11].weight;
					solver.SetEffectorWeights(FullBodyBipedEffector.RightThigh, this.weight * this.nodesMap[10].weight, this.weight * this.nodesMap[10].rotationWeight);
					solver.SetEffectorWeights(FullBodyBipedEffector.RightFoot, this.weight * this.nodesMap[12].weight, this.weight * this.nodesMap[12].rotationWeight);
					return;
				case (OIBoneInfo.BoneGroup)3: return;
				case OIBoneInfo.BoneGroup.LeftLeg:
					solver.leftLegMapping.weight = this.weight * this.nodesMap[8].weight;
					solver.SetEffectorWeights(FullBodyBipedEffector.LeftThigh, this.weight * this.nodesMap[7].weight, this.weight * this.nodesMap[7].rotationWeight);
					solver.SetEffectorWeights(FullBodyBipedEffector.LeftFoot, this.weight * this.nodesMap[9].weight, this.weight * this.nodesMap[9].rotationWeight);
					return;
				default:
					if (_group == OIBoneInfo.BoneGroup.RightArm)
					{
						solver.rightArmMapping.weight = this.weight * this.nodesMap[5].weight;
						solver.SetEffectorWeights(FullBodyBipedEffector.RightShoulder, this.weight * this.nodesMap[4].weight, this.weight * this.nodesMap[4].rotationWeight);
						solver.SetEffectorWeights(FullBodyBipedEffector.RightHand, this.weight * this.nodesMap[6].weight, this.weight * this.nodesMap[6].rotationWeight);
						return;
					}
					if (_group != OIBoneInfo.BoneGroup.LeftArm) return;

					solver.leftArmMapping.weight = this.weight * this.nodesMap[2].weight;
					solver.SetEffectorWeights(FullBodyBipedEffector.LeftShoulder, this.weight * this.nodesMap[1].weight, this.weight * this.nodesMap[1].rotationWeight);
					solver.SetEffectorWeights(FullBodyBipedEffector.LeftHand, this.weight * this.nodesMap[3].weight, this.weight * this.nodesMap[3].rotationWeight);
					return;
			}
		}

		public void SetAllWeight(float value)
		{
			foreach (AdvancedIKControlNode advancedIKControlNode in this.nodes.Values)
			{
				advancedIKControlNode.weight = value;
				advancedIKControlNode.rotationWeight = value;
			}
		}

		public void ResetAllWeight()
		{
			foreach (AdvancedIKControlNode advancedIKControlNode in this.nodes.Values)
			{
				if (advancedIKControlNode.bendGoal != null) continue;
				advancedIKControlNode.weight = 1f;
				if (advancedIKControlNode.target.name.Contains("Spine") || advancedIKControlNode.target.name.Contains("Thigh"))
				{
					advancedIKControlNode.rotationWeight = 0f;
				}
				else
				{
					advancedIKControlNode.rotationWeight = 1f;
				}
			}
		}

		private void OnDestroy()
		{
			foreach (AdvancedIKControlNode advancedIKControlNode in this.nodes.Values)
			{
				Destroy(advancedIKControlNode);
			}
			BaseMgr<AdvancedIKMgr>.Instance.activeControllers.Remove(this);
		}
	}
}
